﻿
using Microsoft.Win32;
using OPCTreeMonitor.SQLdb.dbModel;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Threading;


namespace OPCTreeMonitor.InterfaceWindow
{
    public partial class PLCInterface : Window
    {
        private List<OPCMonitorNode> allData;
        public ObservableCollection<TreeNode> RootNodes { get; set; } = new ObservableCollection<TreeNode>();
        private DispatcherTimer updateTimer;//实时数据更新定时器
        private bool isPlcDisconnectedPromptShown = false; // 记录是否已经提示过 PLC 未连接
        public PLCInterface()
        {
            InitializeComponent();
            DataContext = this;
            InitializeTreeView();
            this.Loaded += PLCInterface_Loaded;
            InitializeUpdateTimer();

            allData = OPCMethod.Instance.GetTreeData();

            // 填充 ComboBox
            var fileNames = allData.Select(x => x.FileName).Distinct().ToList();
            cb_FileName.ItemsSource = fileNames;

            if (fileNames.Count > 0)
            {
                cb_FileName.SelectedIndex = 0;
            }

            PopulateTreeView();
        }
        #region 更新地址中的实时数据
        private void InitializeUpdateTimer()
        {
            updateTimer = new DispatcherTimer
            {
                Interval = TimeSpan.FromSeconds(1) // 1秒更新间隔
            };
            updateTimer.Tick += UpdateTimer_Tick;
        }

        private void UpdateTimer_Tick(object sender, EventArgs e)
        {
            if (!OPCMethod.Instance.GetPlcByIndex(0).Connected)
            {
                if (!isPlcDisconnectedPromptShown)
                {

                    MessageBox.Show("PLC未连接");
                    isPlcDisconnectedPromptShown = true;
                }
                return;
            }
            else
            {
                isPlcDisconnectedPromptShown = false;
            }
            UpdateActualReadValues();
        }

        private void UpdateActualReadValues()
        {
            if (OPCMethod.Instance.GetPlcByIndex(0).Connected)
            {
                if (NodeDataGrid.ItemsSource is IEnumerable<OPCMonitorNode> currentNodes)
                {
                    foreach (var node in currentNodes)
                    {
                        try
                        {
                            if (!string.IsNullOrEmpty(node.NodeRead))
                            {
                                if (node.NodeRead == "XXXX")
                                {
                                    continue;
                                }

                                var result = OPCMethod.Instance.GetPlcByIndex(0)?.ReadData(node.NodeRead);
                                node.ActualRead = string.IsNullOrEmpty(result) ? "ErrorConnect" : result;
                            }
                            else
                            {
                                node.ActualRead = "nullReadNode";
                            }
                        }
                        catch (Exception ex)
                        {
                            node.ActualRead = $"Error: {ex.Message}";
                        }
                    }
                }
            }

        }
        #endregion
        private void PLCInterface_Loaded(object sender, RoutedEventArgs e)
        {
            updateTimer.Start();
        }
        // 在窗口关闭时停止定时器
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            updateTimer.Stop();
        }
        private void InitializeTreeView()
        {
            OPCMethod.Instance.ConncetConfigDb();
            allData = OPCMethod.Instance.GetTreeData();
            // 填充 ComboBox
            var fileNames = allData.Select(x => x.FileName).Distinct().ToList();
            cb_FileName.ItemsSource = fileNames;

            if (fileNames.Count > 0)
            {
                cb_FileName.SelectedIndex = 0;
            }

            PopulateTreeView();
        }
        private void PopulateTreeView()
        {

            string selectedFileName = cb_FileName.SelectedItem as string;
            var filteredData = allData;

            if (!string.IsNullOrEmpty(selectedFileName))
            {
                filteredData = allData.Where(x => x.FileName == selectedFileName).ToList();
            }

            var topLevelNodes = OPCMethod.Instance.BuildTree(filteredData);
            RootNodes.Clear();

            foreach (var node in topLevelNodes)
            {
                RootNodes.Add(ConvertToTreeNode(node));
            }
        }
        private void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
        {
            if (sender is TreeViewItem { DataContext: TreeNode treeNode })
            {
                SortTreeNodeChildren(treeNode);
            }
        }
        private void SortTreeNodeChildren(TreeNode node)
        {
            if (node?.Children == null) return;

            // 修改排序规则：通过ImagePath判断节点类型
            var orderedChildren = node.Children
                .OrderBy(n => n.ImagePath.Contains("根节点.png") ? 1 : 0)  // 组节点在后（值为1）
                .ThenBy(n => n.NodeName)                                   // 按名称排序
                .ToList();

            // 清空后重新添加已排序的节点
            node.Children.Clear();
            foreach (var child in orderedChildren)
            {
                node.Children.Add(child);
            }

            // 递归排序所有子节点（包含组节点）
            foreach (var child in node.Children)
            {
                SortTreeNodeChildren(child);
            }
        }
        private TreeNode ConvertToTreeNode(TreeViewItem node)
        {
            var treeNode = new TreeNode
            {
                NodeName = node.Header.ToString(),
                ImagePath = node.HasItems ?

                    "pack://application:,,,/OPCTreeMonitor;component/Images/根节点.png" :
                    "pack://application:,,,/OPCTreeMonitor;component/Images/子节点.png"
            };

            // 先添加原始子节点
            var rawChildren = new List<TreeViewItem>();
            foreach (var child in node.Items)
            {
                if (child is TreeViewItem childItem)
                {
                    rawChildren.Add(childItem);
                }
            }

            // 转换时即进行排序
            foreach (var childItem in rawChildren
                .OrderBy(c => c.HasItems)  // 先排无子节点的
                .ThenBy(c => c.Header.ToString()))
            {
                treeNode.Children.Add(ConvertToTreeNode(childItem));
            }

            return treeNode;
        }

        private ObservableCollection<OPCMonitorNode> _filteredData = new();

        private void NodeTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (NodeTreeView.SelectedItem is TreeNode selectedNode)
            {
                _filteredData = new ObservableCollection<OPCMonitorNode>(GetFilteredData(BuildNodePath(selectedNode)));
                //确保NodeDataGrid实现ObservableCollection
                NodeDataGrid.ItemsSource = _filteredData;
                NodeDataGrid.Items.Refresh(); // 强制刷新显示
            }
        }

        private string BuildNodePath(TreeNode node)
        {
            var pathParts = new List<string>();
            var currentNode = node;

            while (currentNode != null)
            {
                pathParts.Insert(0, currentNode.NodeName);
                currentNode = FindParentTreeNode(currentNode);
            }
            return string.Join("/", pathParts);
        }

        private List<OPCMonitorNode> GetFilteredData(string selectedPath)
        {
            var filtered = new List<OPCMonitorNode>();

            var leafNode = allData.FirstOrDefault(item =>
                $"{item.GroupName}/{item.NodeName}".Trim('/') == selectedPath);

            if (leafNode != null)
            {
                filtered.Add(leafNode);
            }
            else
            {
                filtered = allData.Where(item =>
                {
                    string fullPath = $"{item.GroupName}/{item.NodeName}".Trim('/');
                    string[] fullPathParts = fullPath.Split('/');
                    string[] selectedPathParts = selectedPath.Split('/');

                    return fullPathParts.Length == selectedPathParts.Length + 1 &&
                           fullPath.StartsWith(selectedPath + "/");
                }).ToList();
            }

            return filtered;
        }

        private bool IsChildPath(OPCMonitorNode item, string selectedPath)
        {
            string fullPath = $"{item.GroupName}/{item.NodeName}";
            return fullPath.StartsWith(selectedPath + "/");
        }

        private void cb_FileName_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            PopulateTreeView();
        }
        #region 节点操作
        private InterfaceAddWindow AddWindow;
        private InterfaceAddSingle addSingleWindow;

        // 添加组
        private void AddGroupMenuItem_Click(object sender, RoutedEventArgs e)
        {

            if (NodeTreeView.SelectedItem is TreeNode selectedNode)
            {
                string parentPath = BuildNodePath(selectedNode);
                if (AddWindow == null)
                {
                    AddWindow = new InterfaceAddWindow(parentPath);
                    AddWindow.GroupAdded += OnGroupAdded;
                    AddWindow.Closed += (s, e) => AddWindow = null;
                    AddWindow.Topmost = true;
                    AddWindow.Show();
                }
                else
                {
                    AddWindow.WindowState = WindowState.Normal;
                    AddWindow.Activate();
                }
            }
        }

        private void OnGroupAdded(string newGroupPath)
        {
            try
            {
                string selectedFileName = GetSelectedFileName();
                if (string.IsNullOrEmpty(selectedFileName))
                {
                    MessageBox.Show("请选择一个文件名。");
                    return;
                }
                // 数据库操作，传递 FileName
                OPCMethod.Instance.InsertGroupToDb(selectedFileName, newGroupPath);

                // 拆分路径
                var pathParts = newGroupPath.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
                if (pathParts.Length == 0) return;

                // 查找父节点（路径最后一段是新节点）
                var parentPath = string.Join("/", pathParts.Take(pathParts.Length - 1));
                var parentNode = FindTreeNodeByPath(parentPath.Split('/'));

                // 创建新节点
                var newNode = new TreeNode
                {
                    NodeName = pathParts.Last(),
                    ImagePath = "pack://application:,,,/OPCTreeMonitor;component/Images/根节点.png"
                };

                // 添加到父节点
                if (parentNode != null)
                {
                    parentNode.Children.Add(newNode);
                    SortTreeNodeChildren(parentNode);
                }
                else // 根节点情况
                {
                    RootNodes.Add(newNode);
                    SortTreeNodeChildren(RootNodes.First());
                }

                // 更新本地数据
                allData.Add(new OPCMonitorNode
                {
                    FileName = selectedFileName,
                    GroupName = newGroupPath,
                    NodeName = "示例",
                    NodePreSetValue = "XXXX",
                    Type = "XXXX",
                    NodeDescription = "XXXX",
                    NodeWrite = "XXXX",
                    NodeRead = "XXXX"
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show($"添加组时出错: {ex.Message}");
            }
        }
        // 添加单个节点
        private void AddSingleMenuItem_Click(object sender, RoutedEventArgs e)
        {
            if (NodeTreeView.SelectedItem is TreeNode selectedNode)
            {
                string parentPath = BuildNodePath(selectedNode);
                if (addSingleWindow == null)
                {
                    addSingleWindow = new InterfaceAddSingle(parentPath);
                    addSingleWindow.NodeAdded += OnSingleNodeAdded;
                    addSingleWindow.Closed += (s, e) => addSingleWindow = null;
                    addSingleWindow.Topmost = true;
                    addSingleWindow.Show();
                }
                else
                {
                    addSingleWindow.WindowState = WindowState.Normal;
                    addSingleWindow.Activate();
                }
            }
        }
        private void OnSingleNodeAdded(OPCMonitorNode newNode)
        {
            try
            {
                string selectedFileName = GetSelectedFileName();
                if (string.IsNullOrEmpty(selectedFileName))
                {
                    MessageBox.Show("请选择一个文件名。");
                    return;
                }
                // 数据库操作
                var allNodes = OPCMethod.Instance.ConfigDbs.OPCMonitorNodeRepository.GetAll();
                newNode.Index = allNodes.Count > 0 ? allNodes.Max(node => node.Index) + 1 : 1;
                newNode.FileName = selectedFileName;
                OPCMethod.Instance.ConfigDbs.OPCMonitorNodeRepository.Insert(newNode);

                // 查找父节点
                var parentNode = FindTreeNodeByPath(newNode.GroupName.Split('/'));

                // 创建新节点
                var treeNode = new TreeNode
                {
                    NodeName = newNode.NodeName,
                    ImagePath = "pack://application:,,,/OPCTreeMonitor;component/Images/子节点.png"
                };

                // 添加到父节点
                if (parentNode != null)
                {
                    parentNode.Children.Add(treeNode);
                    SortTreeNodeChildren(parentNode);
                }

                // 更新本地数据
                allData.Add(newNode);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"添加节点时出错: {ex.Message}");
            }
        }
        // 删除节点
        private void RemoveMenuItem_Click(object sender, RoutedEventArgs e)
        {
            if (NodeTreeView.SelectedItem is TreeNode selectedNode)
            {
                try
                {
                    var nodePath = BuildNodePath(selectedNode);
                    // 获取SQL Sugar客户端
                    var db = OPCMethod.Instance.ConfigDbs.OPCMonitorNodeRepository.GetDbClient();

                    // 判断是否是组节点（根据图片路径）
                    bool isGroup = selectedNode.ImagePath.Contains("根节点.png");
                    string groupPath = isGroup ? nodePath : null;

                    // 删除数据库记录
                    if (isGroup)
                    {
                        // 删除所有属于该组及其子组的记录（SQL Sugar条件删除）
                        var deleteCount = db.Deleteable<OPCMonitorNode>()
                            .Where(e => e.GroupName == groupPath || e.GroupName.StartsWith(groupPath + "/"))
                            .ExecuteCommand(); // 直接执行删除
                    }
                    else
                    {
                        // 删除单个节点（通过路径匹配）
                        var deleteCount = db.Deleteable<OPCMonitorNode>()
                            .Where(e => $"{e.GroupName}/{e.NodeName}".Trim('/') == nodePath)
                            .ExecuteCommand();
                    }

                    // 更新本地数据
                    if (isGroup)
                    {
                        allData.RemoveAll(e =>
                            e.GroupName == groupPath ||
                            e.GroupName.StartsWith(groupPath + "/"));
                    }
                    else
                    {
                        var itemToRemove = allData.FirstOrDefault(e =>
                            $"{e.GroupName}/{e.NodeName}".Trim('/') == nodePath);
                        if (itemToRemove != null)
                            allData.Remove(itemToRemove);
                    }

                    // 从树形结构中移除节点
                    var parentNode = FindParentTreeNode(selectedNode);
                    if (parentNode != null)
                    {
                        parentNode.Children.Remove(selectedNode);
                        SortTreeNodeChildren(parentNode);
                    }
                    else
                    {
                        RootNodes.Remove(selectedNode);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"删除失败: {ex.Message}\n{ex.InnerException?.Message}");
                }
            }
        }
        #region 组导入导出
        private void InputCSVMenuItem_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                OpenFileDialog openFileDialog = new OpenFileDialog
                {
                    Title = "选择要导入的 CSV 文件",
                    Filter = "CSV 文件 (*.csv)|*.csv",
                    Multiselect = false
                };

                if (openFileDialog.ShowDialog() == true)
                {
                    string filePath = openFileDialog.FileName;
                    var csvLines = File.ReadAllLines(filePath, Encoding.UTF8).Skip(1).ToList();
                    var records = new List<OPCMonitorNode>();
                    int errorCount = 0;
                    StringBuilder errorLog = new StringBuilder();

                    // 解析CSV记录
                    for (int i = 0; i < csvLines.Count; i++)
                    {
                        try
                        {
                            string line = csvLines[i];
                            var fields = ParseCsvLine(line).ToArray();
                            if (fields.Length != 9)
                                throw new FormatException($"字段数量不正确（应为9列，实际{fields.Length}列）");

                            records.Add(new OPCMonitorNode
                            {
                                Index = int.Parse(fields[0]),
                                FileName = fields[1],
                                GroupName = fields[2],
                                NodeName = fields[3],
                                Type = fields[4],
                                NodeDescription = fields[5],
                                NodePreSetValue = fields[6],
                                NodeRead = fields[7],
                                NodeWrite = fields[8]
                            });
                        }
                        catch (Exception ex)
                        {
                            errorCount++;
                            errorLog.AppendLine($"第 {i + 2} 行错误: {ex.Message}");
                        }
                    }

                    if (records.Count > 0)
                    {
                        var db = OPCMethod.Instance.ConfigDbs.OPCMonitorNodeRepository.GetDbClient();
                        // SQL Sugar事务
                        db.Ado.BeginTran(); // 替代EF的BeginTransaction()
                        try
                        {
                            // 清空原有数据（替代EF的RemoveRange）
                            db.Deleteable<OPCMonitorNode>().ExecuteCommand();
                            // 批量插入新数据（替代EF的AddRange）
                            db.Insertable(records).ExecuteCommand();

                            db.Ado.CommitTran(); // 提交事务

                            // 更新本地数据
                            allData = records;
                            var fileNames = allData.Select(x => x.FileName).Distinct().ToList();
                            cb_FileName.ItemsSource = fileNames;
                            if (fileNames.Count > 0) cb_FileName.SelectedIndex = 0;
                            PopulateTreeView();

                            MessageBox.Show($"成功导入 {records.Count} 条记录", "导入完成", MessageBoxButton.OK, MessageBoxImage.Information);
                        }
                        catch (Exception ex)
                        {
                            db.Ado.RollbackTran(); // 回滚事务
                            throw new Exception("数据库操作失败: " + ex.Message, ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"导入失败: {ex.Message}\n{ex.InnerException?.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void OutputCSVMenuItem_Click(object sender, RoutedEventArgs e)
        {
            if (NodeTreeView.SelectedItem is TreeNode selectedNode)
            {
                try
                {
                    string selectedPath = BuildNodePath(selectedNode);
                    var filteredData = allData.Where(item =>
                        $"{item.GroupName}/{item.NodeName}".StartsWith(selectedPath + "/") ||
                        $"{item.GroupName}/{item.NodeName}" == selectedPath).ToList();

                    SaveFileDialog saveFileDialog = new SaveFileDialog
                    {
                        Title = "导出组数据",
                        Filter = "CSV 文件 (*.csv)|*.csv",
                        FileName = $"{selectedNode.NodeName}_Export.csv"
                    };

                    if (saveFileDialog.ShowDialog() == true)
                    {
                        using (var writer = new StreamWriter(saveFileDialog.FileName, false, Encoding.UTF8))
                        {
                            writer.WriteLine("Index,FileName,GroupName,NodeName,Type,NodeDescription,NodePreSetValue,NodeRead,NodeWrite");

                            foreach (var node in filteredData)
                            {


                                writer.WriteLine(
                                    $"{node.Index}," +
                                    $"{EscapeCsvField(node.FileName)}," +
                                    $"{EscapeCsvField(node.GroupName)}," +
                                    $"{EscapeCsvField(node.NodeName)}," +
                                    $"{EscapeCsvField(node.Type)}," +
                                    $"{EscapeCsvField(node.NodeDescription)}," +
                                    $"{EscapeCsvField(node.NodePreSetValue)}," +
                                    $"{EscapeCsvField(node.NodeRead)}," +
                                    $"{EscapeCsvField(node.NodeWrite)}");
                            }
                        }
                        MessageBox.Show($"成功导出 {filteredData.Count} 个节点");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"导出失败: {ex.Message}");
                }
            }
        }
        #endregion

        #endregion
        #region dataGrid关联数据库

        /// <summary>
        /// 按钮写入
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WriteNode_Click(object sender, RoutedEventArgs e)
        {
            var button = sender as Button;
            if (button?.CommandParameter is OPCMonitorNode currentNode)
            {
                try
                {
                    var plc = OPCMethod.Instance.GetPlcByIndex(0);
                    if (string.IsNullOrEmpty(currentNode.NodeWrite))
                    {
                        MessageBox.Show("写入地址为空");
                        return;
                    }
                    try
                    {
                        NodeDataGrid.CommitEdit();
                        if (OPCMethod.Instance.ConfigDbs.OPCMonitorNodeRepository.Update(currentNode))
                        {
                            // 更新本地缓存
                            var existingNode = allData.FirstOrDefault(n => n.Index == currentNode.Index);
                            if (existingNode != null)
                            {
                                existingNode.NodePreSetValue = currentNode.NodePreSetValue;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                    plc.SetPLCVar(currentNode.NodeWrite, currentNode.NodePreSetValue);
                    currentNode.ActualRead = OPCMethod.Instance.GetPlcByIndex(0).ReadData(currentNode.NodeRead);
                    MessageBox.Show("写入成功");

                }
                catch (Exception ex)
                {
                    MessageBox.Show($"写入异常: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 保存单个节点的预设值到数据库
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SaveSingle_Click(object sender, RoutedEventArgs e)
        {
            // 获取当前行的数据对象
            var button = sender as Button;
            if (button?.CommandParameter is OPCMonitorNode editedNode)
            {
                try
                {
                    NodeDataGrid.CommitEdit();

                    bool isSuccess = OPCMethod.Instance.ConfigDbs.OPCMonitorNodeRepository.Update(editedNode);

                    if (isSuccess)
                    {
                        // 更新本地缓存
                        var existingNode = allData.FirstOrDefault(n => n.Index == editedNode.Index);
                        if (existingNode != null)
                        {
                            existingNode.NodeName = editedNode.NodeName;
                            existingNode.NodeDescription = editedNode.NodeDescription;
                            existingNode.NodePreSetValue = editedNode.NodePreSetValue;
                        }
                        MessageBox.Show("保存成功！");
                    }
                    else
                    {
                        MessageBox.Show("保存失败：数据库更新未成功");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"保存失败: {ex.Message}");
                }
            }
        }
        /// <summary>
        /// 下载到PLC中
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_loadToPlc_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // 收集所有待写入的节点（过滤无效数据）
                var validNodes = allData
                    .Where(n => !string.IsNullOrEmpty(n.NodeWrite) && !string.IsNullOrEmpty(n.NodePreSetValue))
                    .ToList();

                if (validNodes.Count == 0)
                {
                    MessageBox.Show("没有可写入的有效节点数据", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }

                var plc = OPCMethod.Instance.GetPlcByIndex(0);
                int successCount = 0;
                foreach (var node in validNodes)
                {
                    try
                    {
                        plc.SetPLCVar(node.NodeWrite, node.NodePreSetValue);
                       
                        successCount++;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("写入失败");
                    }
                }
                
                MessageBox.Show($"成功写入{successCount}个节点，失败{validNodes.Count - successCount}个", "完成", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"批量写入失败：{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// 调用PLCInterface类中的方法从PLC读取到数据库
        /// </summary>
        /// <returns></returns>
        public void ExecuteReadFromPlc()
        {
            btn_ReadFromPlc_Click(read_fromPlc, new RoutedEventArgs());
        }
        /// <summary>
        /// 调用PLCInterface类中的方法从数据库下载到PLC
        /// </summary>
        /// <returns></returns>
        public void ExecuteToPlc()
        {
            btn_loadToPlc_Click(load_ToPlc, new RoutedEventArgs());
        }
        private async void btn_ReadFromPlc_Click(object sender, RoutedEventArgs e)
        {
            var button = sender as Button;
            if (button == null) return;
            try
            {
                // 1. 校验PLC连接状态
                var plc = OPCMethod.Instance.GetPlcByIndex(0);
                if (!plc.Connected)
                {
                    MessageBox.Show("PLC未连接，无法执行反读取操作", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                var validNodes = allData
                    .Where(n => !string.IsNullOrEmpty(n.NodeRead) && n.NodeRead != "XXXX")
                    .ToList();

                if (validNodes.Count == 0)
                {
                    MessageBox.Show("没有可反读取的有效节点", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }

                button.Content = "读取中...";
                button.IsEnabled = false;

                await Task.Run(() =>
                {
                    int successCount = 0;
                    int errorCount = 0;

                    // 使用SQLSugar获取数据库客户端
                    using (var db = OPCMethod.Instance.ConfigDbs.OPCMonitorNodeRepository.GetDbClient())
                    {
                        foreach (var node in validNodes)
                        {
                            try
                            {
                                var actualValue = plc.ReadData(node.NodeRead);
                                if (!string.IsNullOrEmpty(actualValue) && !actualValue.StartsWith("Error"))
                                {
                                    node.NodePreSetValue = actualValue;

                                    // 使用SQLSugar查询并更新数据
                                    var dbNode = db.Queryable<OPCMonitorNode>()
                                                 .Where(n => n.Index == node.Index)
                                                 .First();

                                    if (dbNode != null)
                                    {
                                        dbNode.NodePreSetValue = actualValue;
                                        db.Updateable(dbNode).ExecuteCommand();
                                        successCount++;
                                    }
                                }
                                else
                                {
                                    errorCount++;
                                }
                            }
                            catch (Exception ex)
                            {
                                errorCount++;
                                MessageBox.Show($"反读取失败：{node.NodeRead} - {ex.Message}");
                            }
                        }
                    }

                    // 在UI线程显示结果并刷新DataGrid
                    Dispatcher.Invoke(() =>
                    {
                        MessageBox.Show($"反读取完成\n成功: {successCount}\n失败: {errorCount}",
                                      "操作完成", MessageBoxButton.OK, MessageBoxImage.Information);
                        // 强制刷新DataGrid
                        RefreshDataGrid();
                    });
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show($"反读取操作失败：{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                // 恢复按钮状态
                button.Content = "读取";
                button.IsEnabled = true;
            }
        }


        // 刷新DataGrid的辅助方法
        private void RefreshDataGrid()
        {
            // 方式1：重新设置ItemsSource（适用于ObservableCollection）
            if (NodeDataGrid.ItemsSource is ObservableCollection<OPCMonitorNode> collection)
            {
                // 强制触发CollectionChanged事件
                NodeDataGrid.ItemsSource = null;
                NodeDataGrid.ItemsSource = collection;
            }
            // 方式2：直接刷新（适用于其他集合类型）
            else
            {
                NodeDataGrid.Items.Refresh();
            }

            // 如果DataGrid绑定的是当前选中节点的数据，还需要重新加载
            if (NodeTreeView.SelectedItem is TreeNode selectedNode)
            {
                _filteredData = new ObservableCollection<OPCMonitorNode>(GetFilteredData(BuildNodePath(selectedNode)));
                NodeDataGrid.ItemsSource = _filteredData;
            }
        }      
        #endregion
        #region 导航条功能
        private InterfaceAddFileName addFileNameWindow;
        private void btn_AddNewFile_Click(object sender, RoutedEventArgs e)
        {

            if (addFileNameWindow == null)
            {
                addFileNameWindow = new InterfaceAddFileName();
                addFileNameWindow.FileNameAdded += OnFileNameAdded;
                addFileNameWindow.Closed += (s, e) => AddWindow = null;
                addFileNameWindow.Topmost = true;
                addFileNameWindow.Show();
            }
            else
            {
                addFileNameWindow.WindowState = WindowState.Normal;
                addFileNameWindow.Activate();
            }

        }
        private void OnFileNameAdded(object sender, FileNameAddedEventArgs e)
        {
            try
            {
                string fileName = e.FileName;
                string groupName = e.GroupName;

                // 插入新的文件和组信息到数据库
                OPCMethod.Instance.InsertGroupToDb(fileName, groupName);

                // 更新本地数据
                allData = OPCMethod.Instance.GetTreeData();

                // 更新 ComboBox 中的文件名列表
                var fileNames = allData.Select(x => x.FileName).Distinct().ToList();
                cb_FileName.ItemsSource = fileNames;

                // 选择新添加的文件名
                cb_FileName.SelectedItem = fileName;

                // 重新填充 TreeView
                PopulateTreeView();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"添加文件和组时出错: {ex.Message}");
            }
        }

        private void btn_InputCsv_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // 创建打开文件对话框
                OpenFileDialog openFileDialog = new OpenFileDialog
                {
                    Title = "选择要导入的 CSV 文件",
                    Filter = "CSV 文件 (*.csv)|*.csv",
                    Multiselect = false
                };

                if (openFileDialog.ShowDialog() == true)
                {
                    string filePath = openFileDialog.FileName;
                    // 读取 CSV 内容
                    var csvLines = File.ReadAllLines(filePath, Encoding.UTF8).Skip(1).ToList(); // 跳过标题行
                                                                                                // 解析 CSV 数据
                    var records = new List<OPCMonitorNode>();
                    int errorCount = 0;
                    StringBuilder errorLog = new StringBuilder();
                    for (int i = 0; i < csvLines.Count; i++)
                    {
                        try
                        {
                            string line = csvLines[i];
                            var fields = ParseCsvLine(line).ToArray();

                            // 校验字段数量
                            if (fields.Length != 9)
                            {
                                throw new FormatException($"字段数量不正确（应为9列，实际{fields.Length}列）");
                            }

                            // 映射到数据模型
                            var record = new OPCMonitorNode
                            {
                                Index = int.Parse(fields[0]),
                                FileName = fields[1],
                                GroupName = fields[2],
                                NodeName = fields[3],
                                Type = fields[4],
                                NodeDescription = fields[5],
                                NodePreSetValue = fields[6],
                                NodeRead = fields[7],
                                NodeWrite = fields[8]
                            };

                            records.Add(record);
                        }
                        catch (Exception ex)
                        {
                            errorCount++;
                            errorLog.AppendLine($"第 {i + 2} 行错误: {ex.Message}");
                        }
                    }
                    // 如果有错误则提示
                    if (errorCount > 0)
                    {
                        MessageBox.Show($"发现 {errorCount} 条错误记录:\n{errorLog}",
                                      "部分数据错误",
                                      MessageBoxButton.OK,
                                      MessageBoxImage.Warning);
                    }
                    // 写入数据库
                    if (records.Count > 0)
                    {
                        // 获取SQL Sugar客户端（替换EF的DbContext）
                        var db = OPCMethod.Instance.ConfigDbs.OPCMonitorNodeRepository.GetDbClient();

                        // 开启SQL Sugar事务
                        db.Ado.BeginTran();
                        try
                        {
                            // 清空原有数据（SQL Sugar删除语法）
                            db.Deleteable<OPCMonitorNode>().ExecuteCommand();

                            // 批量插入新数据（SQL Sugar插入语法）
                            db.Insertable(records).ExecuteCommand();

                            // 提交事务
                            db.Ado.CommitTran();

                            // 更新本地数据
                            allData = records;

                            // 填充 ComboBox
                            var fileNames = allData.Select(x => x.FileName).Distinct().ToList();
                            cb_FileName.ItemsSource = fileNames;
                            if (fileNames.Count > 0)
                            {
                                cb_FileName.SelectedIndex = 0;
                            }
                            PopulateTreeView();
                            MessageBox.Show($"成功导入 {records.Count} 条记录",
                                          "导入完成",
                                          MessageBoxButton.OK,
                                          MessageBoxImage.Information);
                        }
                        catch (Exception ex)
                        {
                            // 回滚事务
                            db.Ado.RollbackTran();
                            throw new Exception("数据库操作失败: " + ex.Message, ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"导入失败: {ex.Message}\n{ex.InnerException?.Message}",
                              "错误",
                              MessageBoxButton.OK,
                              MessageBoxImage.Error);
            }
        }


        // CSV 解析方法（处理带引号的字段）
        private List<string> ParseCsvLine(string line)
        {
            var fields = new List<string>();
            var buffer = new StringBuilder();
            bool inQuotes = false;

            for (int i = 0; i < line.Length; i++)
            {
                char c = line[i];

                if (c == '"')
                {
                    // 处理双引号转义（""）
                    if (i < line.Length - 1 && line[i + 1] == '"')
                    {
                        buffer.Append('"');
                        i++; // 跳过下一个引号
                    }
                    else
                    {
                        inQuotes = !inQuotes;
                    }
                }
                else if (c == ',' && !inQuotes)
                {
                    fields.Add(buffer.ToString().Trim());
                    buffer.Clear();
                }
                else
                {
                    buffer.Append(c);
                }
            }

            // 添加最后一个字段
            fields.Add(buffer.ToString().Trim());
            return fields;
        }
        private void btn_OutputCsv_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // 创建保存文件对话框
                SaveFileDialog saveFileDialog = new SaveFileDialog
                {
                    Title = "导出 CSV 文件",                    // 对话框标题
                    Filter = "CSV 文件 (*.csv)|*.csv",          // 文件类型过滤
                    DefaultExt = "csv",                        // 默认扩展名
                    FileName = "PLCInterface_Export.csv",       // 默认文件名
                    OverwritePrompt = true                      // 覆盖文件时提示
                };

                // 显示对话框并等待用户选择
                if (saveFileDialog.ShowDialog() == true)
                {
                    string filePath = saveFileDialog.FileName;  // 获取用户选择的路径

                    // 获取数据库全部数据（使用SQL Sugar查询）
                    var db = OPCMethod.Instance.ConfigDbs.OPCMonitorNodeRepository.GetDbClient();
                    var allNodes = db.Queryable<OPCMonitorNode>().ToList();  // 替换EF的Set<T>()

                    // 写入 CSV 文件（UTF-8 带 BOM）
                    using (var writer = new StreamWriter(filePath, false, new UTF8Encoding(true)))
                    {
                        // 写入表头
                        writer.WriteLine("Index,FileName,GroupName,NodeName,Type,NodeDescription,NodePreSetValue,NodeRead,NodeWrite");

                        // 逐行写入数据
                        foreach (var node in allNodes)
                        {
                            // 处理字段中的特殊字符（如逗号、引号）
                            string escapedGroupName = EscapeCsvField(node.GroupName);
                            string escapedNodeName = EscapeCsvField(node.NodeName);
                            string escapedDescription = EscapeCsvField(node.NodeDescription);

                            // 拼接 CSV 行
                            writer.WriteLine(
                                $"{node.Index}," +
                                $"{EscapeCsvField(node.FileName)}," +
                                $"{escapedGroupName}," +
                                $"{escapedNodeName}," +
                                $"{EscapeCsvField(node.Type)}," +
                                $"{escapedDescription}," +
                                $"{EscapeCsvField(node.NodePreSetValue)}," +
                                $"{EscapeCsvField(node.NodeRead)}," +
                                $"{EscapeCsvField(node.NodeWrite)}"
                            );
                        }
                    }

                    MessageBox.Show("导出成功");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"导出失败: {ex.Message}",
                              "错误",
                              MessageBoxButton.OK,
                              MessageBoxImage.Error);
            }
        }

        // 辅助方法：处理 CSV 字段中的特殊字符
        private string EscapeCsvField(string field)
        {
            if (string.IsNullOrEmpty(field)) return "";

            // 如果字段包含逗号、换行符或双引号，则用双引号包裹并转义内部的双引号
            if (field.Contains(",") || field.Contains("\"") || field.Contains("\n"))
            {
                return $"\"{field.Replace("\"", "\"\"")}\"";
            }
            return field;
        }
        #endregion
        #region 辅助方法
        private TreeNode FindTreeNodeByPath(string[] pathParts)
        {
            if (pathParts.Length == 0 || (pathParts.Length == 1 && string.IsNullOrEmpty(pathParts[0])))
                return null;

            TreeNode currentNode = RootNodes.FirstOrDefault(n => n.NodeName == pathParts[0]);
            if (currentNode == null) return null;

            for (int i = 1; i < pathParts.Length; i++)
            {
                currentNode = currentNode.Children.FirstOrDefault(n => n.NodeName == pathParts[i]);
                if (currentNode == null) break;
            }
            return currentNode;
        }

        private TreeNode FindParentTreeNode(TreeNode childNode)
        {
            foreach (var rootNode in RootNodes)
            {
                var parent = FindParentRecursive(rootNode, childNode);
                if (parent != null) return parent;
            }
            return null;
        }

        private TreeNode FindParentRecursive(TreeNode currentNode, TreeNode targetNode)
        {
            if (currentNode.Children.Contains(targetNode)) return currentNode;
            foreach (var child in currentNode.Children)
            {
                var result = FindParentRecursive(child, targetNode);
                if (result != null) return result;
            }
            return null;
        }

        private string GetSelectedFileName()
        {
            return cb_FileName.SelectedItem as string;
        }
        #endregion
        /// <summary>
        /// 点击Bool类型的Label时切换True/False状态
        /// </summary>
        private void BoolLabel_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            // 获取点击的Label控件
            var label = sender as Label;
            if (label == null) return;
            var node = label.DataContext as OPCTreeMonitor.SQLdb.dbModel.OPCMonitorNode;
            if (node == null) return;
            node.NodePreSetValue = node.NodePreSetValue == "TRUE" ? "FALSE" : "TRUE";
        }

    }

    
}
